//===----------------------------------------------------------------------===//
//
//                         BusTub
//
// rwlatch.h
//
// Identification: src/include/common/rwlatch.h
//
// Copyright (c) 2015-2019, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#pragma once

#include <climits>
#include <condition_variable>  // NOLINT
#include <mutex>               // NOLINT

#include "common/macros.h"

/**
 * Reader-Writer latch backed by std::mutex.
 */
class ReaderWriterLatch {
    using mutex_t = std::mutex;
    using cond_t = std::condition_variable;
    static const uint32_t MAX_READERS = UINT_MAX;

   public:
    ReaderWriterLatch() = default;
    ~ReaderWriterLatch() { std::lock_guard<mutex_t> guard(mutex_); }

    DISALLOW_COPY(ReaderWriterLatch);

    /**
     * Acquire a write latch.
     */
    void WLock();

    /**
     * Release a write latch.
     */
    void WUnlock();

    /**
     * Acquire a read latch.
     */
    void RLock();

    /**
     * Release a read latch.
     */
    void RUnlock();

   private:
    mutex_t mutex_;
    cond_t writer_;
    cond_t reader_;
    uint32_t reader_count_{0};
    bool writer_entered_{false};
};
